/* 
 * File:   main.cpp
 * Author: Chen Liu
 *
 * Created on September 21, 2012, 12:39 PM
 */

/*
 * After few tests with different inputs, I found that the Optimal algorithm has 
 * the best performance, which is much better than other five algorithms(in most
 * test, the number of page faults of Optimal algorithms is 20% less than the 
 * other five algorithms). The FIFO, Random, LRU, LFU and SecondChance algorithm
 * almost have the same performance (in most test, the difference between these
 * five algorithms is less than 2%).
 * 
 * When the page number increase from 100 to 500 to 1000 with the other inputs 
 * unchanged, the page faults of all algorithms increase slightly(change is less
 * than 10% with the page number changed from 100 to 1000). At the same 
 * time, if only change the frame number, for all algorithms, the page faults 
 * will decrease slightly with the increasing frames number. When the page number
 * equal to the page reference number, with the increasing of frames number, the
 * number of page fault there is almost no change for the FIFO, Random, LRU, LFU
 * and SecondChance algorithm, and only slight change for Optimal algorithm
 * (approximately 5% for each increment).
 * 
 * If only change the page reference number, and keeping other input unchanged, 
 * the number of page fault for different algorithms has relationships: if the 
 * page reference number change to X times by itself, the number of page fault 
 * will also change the X times.
 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include "pager.h"

using namespace std;


int main(int argc, char **argv)
{
    int seed, min_frames, max_frames, frame_increment, page_num, page_ref_num;
    
    cout << "Enter rand seed: ";
    cin >> seed;
    cout << "Enter min no. of frames: ";
    cin >> min_frames;
    cout << "Enter max no. of frames: ";
    cin >> max_frames;
    cout << "Enter frame increment: ";
    cin >> frame_increment;
    cout << "Enter no. of pages: ";
    cin >> page_num;
    cout << "Enter no. of page refs: ";
    cin >> page_ref_num;
    
    /*
    seed=1234;
    min_frames=10;
    max_frames=50;
    frame_increment=10;
    page_num=100;
    page_ref_num=5000;
    */
    vector<int> page_ref(page_ref_num);

    srand(seed);
    for (int i=0; i<page_ref_num; i++) {
        page_ref[i] = random() % page_num;
    }
    int colNum = (int)ceil((max_frames - min_frames) / (float)frame_increment) + 1;
    vector<Pager> fifoPager(colNum);
    vector<Pager> randomPager(colNum);
    vector<Pager> lruPager(colNum);
    vector<Pager> lfuPager(colNum);
    vector<Pager> scPager(colNum);
    vector<Pager> oprPager(colNum);

    for (int i=0; i<colNum-1; i++) {
        fifoPager[i].Init(eFIFO, min_frames + i * frame_increment);
        randomPager[i].Init(eRandom, min_frames + i * frame_increment);
        lruPager[i].Init(eLRU, min_frames + i * frame_increment);
        lfuPager[i].Init(eLFU, min_frames + i * frame_increment);
        scPager[i].Init(eSecondChance, min_frames + i * frame_increment);
        oprPager[i].Init(eOptimalPageReplacement, min_frames + i * frame_increment);
        lruPager[i].SetPageNum(page_num);
        lfuPager[i].SetPageNum(page_num);
        oprPager[i].SetPageRefs(page_ref);
    }
    fifoPager[colNum-1].Init(eFIFO, max_frames);
    randomPager[colNum-1].Init(eRandom, max_frames);
    lruPager[colNum-1].Init(eLRU, max_frames);
    lfuPager[colNum-1].Init(eLFU, max_frames);
    scPager[colNum-1].Init(eSecondChance, max_frames);
    oprPager[colNum-1].Init(eOptimalPageReplacement, max_frames);
    lruPager[colNum-1].SetPageNum(page_num);
    lfuPager[colNum-1].SetPageNum(page_num);
    oprPager[colNum-1].SetPageRefs(page_ref);
   
    for (int i=0; i<page_ref_num; i++) {
        for (int j=0; j<colNum; j++) {
            fifoPager[j].AccessPage(page_ref[i]);
            randomPager[j].AccessPage(page_ref[i]);
            lruPager[j].AccessPage(page_ref[i]);
            lfuPager[j].AccessPage(page_ref[i]);
            scPager[j].AccessPage(page_ref[i]);
            oprPager[j].AccessPage(page_ref[i]);
        }
    }

    cout << endl;
    cout << "\t\tPAGE FAULTS" << endl;
    cout << "Frames: " << "\t";
    for (int i=0; i<colNum-1; i++)
        cout << min_frames + i * frame_increment << "\t";
    cout << max_frames << endl;
    cout << "FIFO: " << "\t\t";
    for (int i=0; i<colNum; i++)
        cout << fifoPager[i].GetPageFaults() << "\t";
    cout << endl;

    cout << "Random: " << "\t";
    for (int i=0; i<colNum; i++)
        cout << randomPager[i].GetPageFaults() << "\t";
    cout << endl;

    cout << "LRU: " << "\t\t";
    for (int i=0; i<colNum; i++)
        cout << lruPager[i].GetPageFaults() << "\t";
    cout << endl;

    cout << "LFU: " << "\t\t";
    for (int i=0; i<colNum; i++)
        cout << lfuPager[i].GetPageFaults() << "\t";
    cout << endl;

    cout << "2ndChance: " << "\t";
    for (int i=0; i<colNum; i++)
        cout << scPager[i].GetPageFaults() << "\t";
    cout << endl;

    cout << "Optimal: " << "\t";
    for (int i=0; i<colNum; i++)
        cout << oprPager[i].GetPageFaults() << "\t";
    cout << endl;


    return 0;
}

